package mygame;
 
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import tools.MultiFaceBox;
 
/** Sample 8 - how to let the user pick (select) objects in the scene 
 * using the mouse or key presses. Can be used for shooting, opening doors, etc. */
public class Main extends SimpleApplication {
 
  public static void main(String[] args) {
    Main app = new Main();
    app.start();
  }
    Node shootables;
    Geometry mark;
    protected Geometry player;
    private Vector3f airplanePosition = new Vector3f(0f,0f,0f);
    private Quaternion airplaneDirection = new Quaternion().fromAngleAxis( FastMath.PI/2 , new Vector3f(0,1,0));
    int airplaneSpeed = 0;
  
    private BulletAppState bulletAppState;
    private RigidBodyControl airplane;
    private Box b;
    
    
   @Override
  public void simpleInitApp() {
    initCamera();
    initCrossHairs(); // a "+" in the middle of the screen to help aiming
    initKeys();       // load custom key mappings
    initMark();       // a red sphere to mark the hit
    
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);

    /** create four colored boxes and a floor to shoot at: */
    shootables = new Node("Shootables");
    rootNode.attachChild(shootables);
    shootables.attachChild(makeCube("Blue", ColorRGBA.Blue, 3f, 0f, 0f));
    shootables.attachChild(makeCube("Green", ColorRGBA.Green, 6f, 0f, 0f));
    shootables.attachChild(makeCube("Red", ColorRGBA.Red, 9f, 0f, 0f));
    shootables.attachChild(makeCube("Yellow", ColorRGBA.Yellow, 12f, 0f, 0f));
    shootables.attachChild(makeFloor());
    
    /** player - airplane */
    b = new Box(airplanePosition, 1, 1, 1);
    player = new Geometry("Player", b);
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.White);
    player.setMaterial(mat);
    player.setLocalRotation(airplaneDirection);
    
    airplane = new RigidBodyControl(2f);
    player.addControl(airplane);
    bulletAppState.getPhysicsSpace().add(airplane);
    
    rootNode.attachChild(player);
    airplane.setGravity(airplanePosition);
    
  }
 
  /** Declaring the "Shoot" action and mapping to its triggers. */
  private void initKeys() {
    inputManager.addMapping("Shoot",
      new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar
      new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click
    inputManager.addListener(actionListener, "Shoot");
    
    // You can map one or several inputs to one named action
    inputManager.addMapping("SpeedUp",  new KeyTrigger(KeyInput.KEY_NUMPAD5));
    inputManager.addMapping("SpeedDown",   new KeyTrigger(KeyInput.KEY_NUMPAD2));
    inputManager.addMapping("RotateUp", new KeyTrigger(KeyInput.KEY_NUMPAD1));
    inputManager.addMapping("RotateDown", new KeyTrigger(KeyInput.KEY_NUMPAD3));
    // Add the names to the action listener.
    inputManager.addListener(analogListener, new String[]{"SpeedUp", "SpeedDown", "RotateUp", "RotateDown"});
    
    
  }
  
    private AnalogListener analogListener = new AnalogListener() {
    public void onAnalog(String name, float value, float tpf) {
        Vector3f change;
        if (name.equals("RotateUp")) {
//          player.rotate(0, 0, value*speed);
//          airplaneDirection = new Vector3f(0f,0f,value*speed);
//            airplaneDirection = player.getLocalRotation().fromAngleAxis(FastMath.PI*1/180, new Vector3f(1,0,0));
        }
        if (name.equals("RotateDown")){
//          player.rotate(0, 0, -value*speed);
//          airplaneDirection = new Vector3f(0f,0f,-value*speed);
        }
        if (name.equals("SpeedUp")) {
//          Vector3f v = player.getLocalTranslation();
//          player.setLocalTranslation(v.x + value*speed, v.y, v.z);
            airplaneSpeed++;
        }
        if (name.equals("SpeedDown")) {
//          Vector3f v = player.getLocalTranslation();
//          player.setLocalTranslation(v.x - value*speed, v.y, v.z);
            airplaneSpeed--;
        }
    }
  };
  
  
  
  /** Defining the "Shoot" action: Determine what was hit and how to respond. */
  private ActionListener actionListener = new ActionListener() {
 
    public void onAction(String name, boolean keyPressed, float tpf) {
      if (name.equals("Shoot") && !keyPressed) {
        makeShot();
      }
    }

    private void makeShot() {
            // 1. Reset results list.
        CollisionResults results = new CollisionResults();
        // 2. Aim the ray from cam loc to cam direction.
        Quaternion rot = player.getWorldRotation();
        Vector3f dir = rot.getRotationColumn(2);
        Ray ray = new Ray(player.getLocalTranslation(), dir);
        // 3. Collect intersections between Ray and Shootables in results list.
        shootables.collideWith(ray, results);
        // 4. Print the results
        System.out.println("----- Collisions? " + results.size() + "-----");
        for (int i = 0; i < results.size(); i++) {
          // For each hit, we know distance, impact point, name of geometry.
          float dist = results.getCollision(i).getDistance();
          Vector3f pt = results.getCollision(i).getContactPoint();
          String hit = results.getCollision(i).getGeometry().getName();
          System.out.println("* Collision #" + i);
          System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
        }
        // 5. Use the results (we mark the hit object)
        if (results.size() > 0) {
          // The closest collision point is what was truly hit:
          CollisionResult closest = results.getClosestCollision();
          // Let's interact - we mark the hit with a red dot.
          mark.setLocalTranslation(closest.getContactPoint());
          rootNode.attachChild(mark);
        } else {
          // No hits? Then remove the red mark.
          rootNode.detachChild(mark);
        }
    }
  };
 
  /** A cube object for target practice */
  protected Geometry makeCube(String name, ColorRGBA color, float x, float y, float z) {
    Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);
    Geometry cube = new Geometry(name, box);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", color);
    cube.setMaterial(mat1);
    return cube;
  }
 
  /** A floor to show that the "shot" can go through several objects. */
  protected Geometry makeFloor() {
    Box box = new Box(new Vector3f(0, -4, -5), 15, .2f, 15);
    Geometry floor = new Geometry("the Floor", box);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", ColorRGBA.Gray);
    floor.setMaterial(mat1);
    return floor;
  }
 
  /** A red ball that marks the last spot that was "hit" by the "shot". */
  protected void initMark() {
    Sphere sphere = new Sphere(30, 30, 0.2f);
    mark = new Geometry("BOOM!", sphere);
    Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mark_mat.setColor("Color", ColorRGBA.Red);
    mark.setMaterial(mark_mat);
  }
 
  /** A centred plus sign to help the player aim. */
  protected void initCrossHairs() {
    guiNode.detachAllChildren();
    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
    BitmapText ch = new BitmapText(guiFont, false);
    ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
    ch.setText("+"); // crosshairs
    ch.setLocalTranslation( // center
      settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
      settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
    guiNode.attachChild(ch);
  }

    private void initCamera() {
        cam.setLocation(new Vector3f(0f,0f,10f));
        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
    }

    public void simpleUpdate(float tpf) {
        // Speed
//        Vector3f v = player.getLocalTranslation();
        Vector3f direction = airplaneDirection.getRotationColumn(2);
//        v.addLocal(direction.mult(airplaneSpeed*tpf));
//        player.setLocalTranslation(v);
//        // Rotation
//        player.setLocalRotation(airplaneDirection);
        
        airplane.setLinearVelocity(direction.mult(airplaneSpeed));
        
        
    }
    
    
}